
/*
*		@author 	Shawnwill_Chen
*		@file   	OLED.C
*		@project	DEV_For2016
*
*/
#include "i2c_oled.h"
#include "stdarg.h"
#include "string.h"
#include "code.h"
#include "main.h"
#define SCL_1 		HAL_GPIO_WritePin(OLED_SCL_GPIO_Port,OLED_SCL_Pin,GPIO_PIN_SET)  
#define SCL_0 		HAL_GPIO_WritePin(OLED_SCL_GPIO_Port,OLED_SCL_Pin,GPIO_PIN_RESET)
#define SDA_1 		HAL_GPIO_WritePin(OLED_SDA_GPIO_Port,OLED_SDA_Pin,GPIO_PIN_SET)
#define SDA_0 		HAL_GPIO_WritePin(OLED_SDA_GPIO_Port,OLED_SDA_Pin,GPIO_PIN_RESET)

#define XLevelL		0x00
#define XLevelH		0x10
#define XLevel		((XLevelH&0x0F)*16+XLevelL)
#define Max_Column	128
#define Max_Row			64
#define	Brightness	0xFF 

#define X_WIDTH 128
#define Y_WIDTH 64

#define USE_GRAPH_RAM

#ifdef USE_GRAPH_RAM
uint16_t GlobalRamPointPos=0;
#endif


#ifdef USE_GRAPH_RAM
unsigned char GRAM[1024];
#endif
//const unsigned char logoUESTC[] = {
//};//8line 64 colums



static void delay(unsigned int z);

/////////////////////////////////////////////OLED CTR///
/*********************OLED驱动程序用的延时程序************************************/
//static void OLED_GPIO_config()
//{
//	GPIO_InitTypeDef GPIO_InitStructure;
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
//	
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10;         
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     
//	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//	GPIO_Init(GPIOB, &GPIO_InitStructure);
//}

static void delay(unsigned int z)
{
	unsigned int x,y;
	for(x=z;x>0;x--)
		for(y=1;y>0;y--);
}

/**********************************************
//IIC Start
**********************************************/
static void IIC_Start() 
{
   SCL_1; delay(5);
   SDA_1; delay(5); 
   SDA_0; delay(5);  
   SCL_0; delay(5);
}

/**********************************************
//IIC Stop
**********************************************/
static void IIC_Stop()
{
   SCL_0;delay(5);
   SDA_0;delay(5);
   SCL_1;delay(5);
   SDA_1;delay(5);
}

/**********************************************
// 通过I2C总线写一个字节
**********************************************/
void Write_IIC_Byte(unsigned char IIC_Byte)
{
    unsigned char i;
    for(i=0;i<8;i++)             
    {
        if(IIC_Byte & 0x80)
                SDA_1;
        else
                SDA_0;
				delay(5);
        SCL_1;	delay(5);    
        SCL_0;	delay(5);
        IIC_Byte<<=1;  
                       
    }
    SDA_1;	delay(5);
    SCL_1;	delay(5);
    SCL_0;	delay(5);
}
                           
/*********************OLED写数据************************************/ 
void OLED_WrDat(unsigned char IIC_Data)
{
	IIC_Start();
	Write_IIC_Byte(0x78);                   //0111100->Slave address, 0->SA0=0
	Write_IIC_Byte(0x40);			//write data
	Write_IIC_Byte(IIC_Data);
	IIC_Stop();
}
/*********************OLED写命令************************************/
void OLED_WrCmd(unsigned char IIC_Command)
{
	IIC_Start();
	Write_IIC_Byte(0x78);            //0111100->Slave address, 0->SA0=0
	Write_IIC_Byte(0x00);			//write command
	Write_IIC_Byte(IIC_Command);
	IIC_Stop();
}
/*********************OLED 设置坐标************************************/
void oled_set_pos(unsigned char x, unsigned char y) 
{ 
	#ifdef USE_GRAPH_RAM
		GlobalRamPointPos = x + y*128;
	#else
		OLED_WrCmd(0xb0+y);           //设置page，范围b0~b7
		OLED_WrCmd(((x&0xf0)>>4)|0x10);  //set the upper column address
		OLED_WrCmd((x&0x0f)|0x01);//set the lower column address
	#endif
} 

/************write virtual graph ram to oled to reflash************************/
int * p1;
void oled_reflash(void) 
{
	
	unsigned char *ram =  GRAM;
	
	unsigned char y,x;
	for(y=0;y<8;y++)
	{
		OLED_WrCmd(0xb0 + y);
		OLED_WrCmd(0x01);
		OLED_WrCmd(0x10);
        //while(*bmp_dat!='\0')
		for(x=0;x<X_WIDTH;x++)
       OLED_WrDat(*ram++);
	}
}

void oled_fill(unsigned char * bmp_dat) 
{
	unsigned char y,x;
	for(y=0;y<8;y++)
	{
		OLED_WrCmd(0xb0 + y);
		OLED_WrCmd(0x01);
		OLED_WrCmd(0x10);
        //while(*bmp_dat!='\0')
		for(x=0;x<X_WIDTH;x++)
            OLED_WrDat(*bmp_dat++);
	}
}
/*********************OLED复位************************************/
void oled_clear_screen(void)
{
	#ifdef USE_GRAPH_RAM
		memset(GRAM, 0, 1024);
	
	#else
		unsigned char y,x;
		for(y=0;y<8;y++)
		{
			OLED_WrCmd(0xb0+y);
			OLED_WrCmd(0x01);
			OLED_WrCmd(0x10);
			for(x=0;x<X_WIDTH;x++)
				OLED_WrDat(0);
		}
	#endif
}
/*********************OLED初始化************************************/
void oled_init(void)
{
	//OLED_GPIO_config();
	delay(500);//初始化之前的延时很重要！
	
	OLED_WrCmd(0xae);//--turn off oled panel
	OLED_WrCmd(0x00);//---set low column address
	OLED_WrCmd(0x10);//---set high column address
	OLED_WrCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
	OLED_WrCmd(0x81);//--set contrast control register
	OLED_WrCmd(Brightness); // Set SEG Output Current Brightness
	OLED_WrCmd(0xa1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
	OLED_WrCmd(0xc8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
	OLED_WrCmd(0xa6);//--set normal display
	OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
	OLED_WrCmd(0x3f);//--1/64 duty
	OLED_WrCmd(0xd3);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WrCmd(0x00);//-not offset
	OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
	OLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WrCmd(0xd9);//--set pre-charge period
	OLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WrCmd(0xda);//--set com pins hardware configuration
	OLED_WrCmd(0x12);
	OLED_WrCmd(0xdb);//--set vcomh
	OLED_WrCmd(0x40);//Set VCOM Deselect Level
	OLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
	OLED_WrCmd(0x02);//
	OLED_WrCmd(0x8d);//--set Charge Pump enable/disable
	OLED_WrCmd(0x14);//--set(0x10) disable
	OLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
	OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7) 
	OLED_WrCmd(0xaf);//--turn on oled panel
	oled_fill(0x00); //初始清屏
	oled_set_pos(0,0);
} 

void oled_printf(unsigned char x, unsigned char y, const char* fmt,...){
	//oled_set_pos(x, y);
	char buff[128] = {0};
	va_list ap;
	va_start(ap, fmt);
	vsprintf(buff, fmt, ap);
	
	oled_p6x8str(0,x,y, buff);
	va_end(ap);
	
}

//=============================数字显示函数=============================
//显示3个数字的数字串
void oled_disNum(unsigned char inv, unsigned char x, unsigned char y, short num)
{
  unsigned char number[]={"   "};
	if(num < 0){
		num = -num;
		oled_p6x8str(0, x,y, "-");
		x += 6;
	}

  number[0] = num/100		+ 0x30;
	number[1] = num/10%10 + 0x30;
	number[2] = num%10 		+ 0x30;

	oled_p6x8str(0, x,y, (const char*)&number[0]);
	
}

/*****功能描述：显示6*8一组标准ASCII字符串	显示的坐标（x,y），y为页范围0～7******/
void oled_p6x8str(unsigned char inv, unsigned char x, unsigned char y,const char * ch)
{
	unsigned char c=0,i=0,j=0;
	while (ch[j]!='\0')
	{
		c =ch[j]-32;//whole ascii table offset is 28(compare with standard! )
		if(x>X_WIDTH){x=0;y++;}
		oled_set_pos(x,y);
		if(inv)
			for(i=0;i<6;i++){
				#ifdef USE_GRAPH_RAM
					GRAM[GlobalRamPointPos++] = ~F6x8[c][i];
					if(GlobalRamPointPos>=1024)
						GlobalRamPointPos=0;
				#else
					OLED_WrDat(~F6x8[c][i]);
				#endif
			}
		else
			for(i=0;i<6;i++){
				#ifdef USE_GRAPH_RAM
					GRAM[GlobalRamPointPos++] = F6x8[c][i];
					if(GlobalRamPointPos>=1024)
							GlobalRamPointPos=0;
				#else
					OLED_WrDat(F6x8[c][i]);
				#endif
			}
		x+=6;
		j++;
	}                                                                                                                                                                                                                                                                                            
}


void ram_p6x8str(unsigned char inv, unsigned char x, unsigned char y,const char * ch)
{
	                                                                                                                                                                                                                                                                                        
}

/*****功能描述：显示6*8一组标准ASCII字符串	显示的坐标（x,y），y为页范围0～7******/
void oled_p6x8strAndNum(unsigned char inv, unsigned char x, unsigned char y,const char * ch, short num)
{
	unsigned char c=0,i=0,j=0;
	while (ch[j]!='\0')
	{
		c =ch[j]-32;//whole ascii table offset is 28(compare with standard! )
		if(x>X_WIDTH){x=0;y++;}
		oled_set_pos(x,y);
		if(inv){
			for(i=0;i<6;i++){
			#ifdef USE_GRAPH_RAM
				GRAM[GlobalRamPointPos++] = ~F6x8[c][i];
				GlobalRamPointPos>=1024?GlobalRamPointPos=0:GlobalRamPointPos;
			#else 
				OLED_WrDat(~F6x8[c][i]);
			#endif
			}
		}
		else{
			for(i=0;i<6;i++){
			#ifdef USE_GRAPH_RAM
				GRAM[GlobalRamPointPos++] = F6x8[c][i];
				GlobalRamPointPos>=1024?GlobalRamPointPos=0:GlobalRamPointPos;
			#else 
				OLED_WrDat(F6x8[c][i]);
			#endif
			}
		}
		
		x+=6;
		j++;
	}
	oled_p6x8str(inv, x,y,":");
	x+=6;
	if(num<0){
		oled_p6x8str(inv, x,y,"-");
		x+=6;
		num = -num;
	}
	else{
		oled_p6x8str(inv, x,y," ");
		x+=6;
	}
	
	oled_disNum(inv, x,y,num);
	
}
/*****功能描述：显示32x16的1个数字，显示的坐标（x,y），y为页范围0～7******/
/*num 取值从 0 -- 9 */
//void oled_p16x16num(const unsigned char x,const unsigned char y,
//                    const unsigned char num)
//{
//    const unsigned char * p = F32x16_NUM_TAB;
//    if(x>128)return;
//    if(y>7)return;
//    if(num>10)return;
//    
//    p += 32*num;//pointer offset
//    oled_set_pos(x,y);
//    for(char i=0;i<16;i++){
//        OLED_WrDat(*p++);
//    }
//    //上半个字
//    oled_set_pos(x,y+1);
//    for(char i=0;i<16;i++){
//        OLED_WrDat(*p++);
//    }
//}
/***************功能描述：显示16x16一组汉字	显示的坐标（x,y），y为页范围0～7****************/
/*所需汉字需已经存表,一行最多八个字,列行式,阴码，列行式，逆向，16进制，像素大小8，C51，16x16
显示从index开始的num个数，传入数组名*/
void oled_p16x16ch( unsigned char x,      const unsigned char y,
                    const unsigned char index,  const unsigned char num,
                    const  char *p  )
{
    unsigned char i;
    if(x>128)return;
    if(y>7)return;
    if(num>8)return;
    p += index*32;//set pointer position, one chinese use 32 byte!
    for(char j=0;j< num-index;j++){
        oled_set_pos(x+16*j,y);
        for(i=0; i<16; i++){
            OLED_WrDat(*(p++));
        }
        oled_set_pos(x+16*j,y+1);
        for(i=0;i<16;i++){
            OLED_WrDat(*(p++));
        }
        
    }
}
//浮点型数据显示   只显示十位开始到小数点后3位
void disfloat_num(unsigned char x, unsigned char y,float num)
{
	unsigned char number[]={"     "};
  unsigned char i,j,c;
	uint32_t int_num;
	uint32_t decimal;
  int_num = (int)num;
	decimal = (num - int_num)*1000;
  number[0] = int_num/10;           //十位
  number[1] = int_num%10 ;         //个位
  number[2] = '.';                 //小数点
  number[3] = decimal/100;         //小数点后一位
  number[4] = (decimal/10)%10;      //小数点后第二位
  number[5] = decimal%10;          //小数点后第三位
  oled_set_pos(x,y);
  for(j=0;j<6;j++)
    {
      c = number[j] + 16 ;
      for(i=0;i<6;i++)
			{			
				if(j==2)
				{
					OLED_WrDat(F6x8[14][i]);continue;
				}
				OLED_WrDat(F6x8[c][i]);
			}
		}
			
}



